package com.aos.erp.common.redis.impl;

import com.aos.erp.common.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RedisServiceImpl<K, V> implements RedisService<K, V> {


    @Resource(name = "redisTemplate")
    private RedisTemplate<K, V> redisTemplate;


    //key 操作
    public boolean containsKey(K key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Throwable t) {
            log.error("判断缓存存在失败key[" + key + ", error[" + t + "]");
        }
        return false;
    }

    public boolean removeKey(K key) {
        try {
            redisTemplate.delete(key);
            return true;
        } catch (Throwable t) {
            log.error("移除缓存失败key[" + key + ", error[" + t + "]");
        }
        return false;
    }


    public Long getTimeOutValue(K key) {
        Long expire = -2L;
        try {
            expire = redisTemplate.getExpire(key);

        } catch (Exception e) {
            log.error("获取缓存剩余时间失败key[" + key + ", error[" + e + "]");
        }
        return expire;
    }


    //String 操作
    public boolean saveValue(K key, V value, long time) {
        try {
            ValueOperations<K, V> valueOps = redisTemplate.opsForValue();
            valueOps.set(key, value);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } catch (Throwable t) {
        }
        return false;
    }

    public V getValue(K key) {
        try {
            ValueOperations<K, V> valueOps = redisTemplate.opsForValue();
            return valueOps.get(key);
        } catch (Throwable t) {
            log.error("获取缓存失败key[" + key + ", error[" + t + "]");
        }
        return null;
    }


    //Hash 操作
    public boolean saveHash(K key, String hashKey, V value, long time) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            opsForHash.put(key, hashKey, value);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            log.error("缓存失败key[" + key + ", error[" + e + "]");
        }
        return false;
    }

    public boolean saveHash(K key, Map<String, V> map, long time) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            opsForHash.putAll(key, map);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            log.error("缓存失败key[" + key + ", error[" + e + "]");
        }
        return false;
    }

    public Map<String, V> getHash(K key) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            return opsForHash.entries(key);
        } catch (Exception e) {
            log.error("获取缓存失败key[" + key + ", error[" + e + "]");
        }
        return null;
    }

    public Set<String> getHashKeys(K key) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            return opsForHash.keys(key);
        } catch (Exception e) {
            log.error("获取缓存失败key[" + key + ", error[" + e + "]");
        }
        return null;
    }

    public List<V> getHashValues(K key) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            return opsForHash.values(key);
        } catch (Exception e) {
            log.error("获取缓存失败key[" + key + ", error[" + e + "]");
        }
        return null;
    }

    public Map<String, V> delHash(K key, String... hashKey) {
        try {
            HashOperations<K, String, V> opsForHash = redisTemplate.opsForHash();
            opsForHash.delete(key, hashKey);
            return opsForHash.entries(key);
        } catch (Exception e) {
            log.error("获取缓存失败key[" + key + ", error[" + e + "]");
        }
        return null;
    }

    // list操作 头部（左边）或者尾部（右边）
    public boolean saveListObj(K key, V value, long time) {
        try {
            ListOperations<K, V> listOps = redisTemplate.opsForList();
            listOps.rightPush(key, value);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + value + "]", t);
        }
        return false;
    }

    public boolean saveList(K k, List<V> v, long time) {
        K key = k;
        try {
            if (v != null && v.size() > 0) {
                ListOperations<K, V> listOps = redisTemplate.opsForList();
                listOps.rightPushAll(key, v);
                if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + v + "]", t);
        }
        return false;
    }

    public List<V> getList(K k, long start, long end) {
        K key = k;
        try {
            ListOperations<K, V> listOps = redisTemplate.opsForList();
            return listOps.range(key, start, end);
        } catch (Throwable t) {
            log.error("获取list缓存失败key[" + key + "]" + ", error[" + t + "]");
        }
        return null;
    }

    public long getListSize(K k) {
        K key = k;
        try {
            ListOperations<K, V> listOps = redisTemplate.opsForList();
            return listOps.size(key);
        } catch (Throwable t) {
            log.error("获取list长度失败key[" + key + "], error[" + t + "]");
        }
        return 0;
    }

    public V delList(K k) {
        K key = k;
        try {
            ListOperations<K, V> listOps = redisTemplate.opsForList();
            return listOps.rightPop(key);
        } catch (Throwable t) {
            log.error("移除list缓存失败key[" + key + ", error[" + t + "]");
        }
        return null;
    }

    //Set 操作
    public boolean saveSetObj(K k, V v, long time) {
        K key = k;
        try {
            SetOperations<K, V> valueOps = redisTemplate.opsForSet();
            valueOps.add(key, v);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + v + "]", t);
        }
        return true;
    }

    public boolean saveSet(K k, Set<V> v, long time) {
        K key = k;
        try {
            if (v != null && v.size() > 0) {
                SetOperations<K, V> setOps = redisTemplate.opsForSet();
                setOps.add(key, (V[]) v.toArray());
                if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + v + "]", t);
        }
        return false;
    }

    public Set<V> getSet(K k) {
        K key = k;
        try {
            SetOperations<K, V> setOps = redisTemplate.opsForSet();
            return setOps.members(key);
        } catch (Throwable t) {
            log.error("获取set缓存失败key[" + key + ", error[" + t + "]");
        }
        return null;
    }

    //Sort Set 操作
    public boolean saveZSetObj(K k, V v, double score, long time) {
        K key = k;
        try {
            ZSetOperations<K, V> valueOps = redisTemplate.opsForZSet();
            valueOps.add(key, v, score);
            if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + v + "]", t);
        }
        return true;
    }

    public boolean saveZSet(K k, Set<ZSetOperations.TypedTuple<V>> v, long time) {
        K key = k;
        try {
            if (v != null && v.size() > 0) {
                ZSetOperations<K, V> setOps = redisTemplate.opsForZSet();
                setOps.add(key, v);
                if (time > 0) redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Throwable t) {
            log.error("缓存[" + key + "]失败, value[" + v + "]", t);
        }
        return false;
    }

    public Set<V> getZSet(K k, long start, long end) {
        K key = k;
        try {
            ZSetOperations<K, V> setOps = redisTemplate.opsForZSet();
            return setOps.range(key, start, end);
        } catch (Throwable t) {
            log.error("获取set缓存失败key[" + key + ", error[" + t + "]");
        }
        return null;
    }

    public Set<V> getZSetByScore(K k, double min, double max) {
        K key = k;
        try {
            ZSetOperations<K, V> setOps = redisTemplate.opsForZSet();
            return setOps.rangeByScore(key, min, max);
        } catch (Throwable t) {
            log.error("获取set缓存失败key[" + key + ", error[" + t + "]");
        }
        return null;
    }
}
